package flexconsole.model {
	import flash.xml.XMLDocument;
	import flash.xml.XMLNode;
	
	import flexconsole.AppFacade;
	
	import flexunit.framework.Assert;
	
	import mx.logging.ILogger;
	import mx.logging.Log;
	import mx.rpc.xml.SimpleXMLDecoder;
	import mx.rpc.xml.SimpleXMLEncoder;
	import mx.utils.ObjectUtil;
	
	import org.puremvc.as3.patterns.proxy.Proxy;
	
	/**
	 * Concrete implementation of <code>IConfigProxy</code>.
	 *
	 * @author ivanchoo
	 *
	 */
	public class ConfigProxy extends Proxy implements IConfigProxy {
		
		static private const QNAME:String = "config";
		
		static private var logger:ILogger = Log.getLogger("flexconsole.model.ConfigProxy");
		
		private var _source:XML;
		
		public function ConfigProxy(name:String, source:XML = null) {
			super(name, new Object());
			_source = source;
		}
		
		override public function onRegister():void {
			super.onRegister();
			
			if (_source) {
				source = _source;
			}
			_source = null;
		}
		
		public function get source():XML {
			if (_source) {
				return _source;
			} else {
				var qName:QName = new QName(QNAME);
				var xDoc:XMLDocument = new XMLDocument();
				var encoder:SimpleXMLEncoder = new SimpleXMLEncoder(xDoc);
				var xNode:XMLNode = encoder.encodeValue(data ? data : {}, qName, xDoc);
				return new XML(xDoc.toString());
			}
		}
		
		public function set source(xml:XML):void {
			if (xml) {
				var decoder:SimpleXMLDecoder = new SimpleXMLDecoder(false);
				var obj:Object = decoder.decodeXML(new XMLDocument(xml.toXMLString()));
				data = obj && obj.hasOwnProperty(QNAME) ? obj[QNAME] : new Object();
			} else {
				data = new Object();
			}
			sendNotification(AppFacade.DATA_CHANGE, null, getProxyName());
		}
		
		public function getValue(key:String, defaultValue:* = null):* {
			Assert.assertNotNull(key);
			return data.hasOwnProperty(key) ? data[key] : defaultValue;
		}
		
		public function setValue(key:String, value:* = null):void {
			Assert.assertNotNull(key);
			logger.debug("setValue({0}, {1})", key, value);
			var oldValue:* = getValue(key);
			
			if (ObjectUtil.compare(value, oldValue) === 0) {
				logger.warn("Key '{0}' of value '{1}' has not changed, no notification is sent.", key, value);
				return;
			}
			
			if (value == null) {
				if (data.hasOwnProperty(key)) {
					delete data[key];
				}
			} else {
				data[key] = value;
			}
			sendNotification(AppFacade.DATA_CHANGE, key, getProxyName());
		
		}
	
	}
}